package edu.hawaii.senin.iclouds.basics;

/**
 * 
 * Defines class for Molecule.
 * 
 * @author Pavel Senin.
 * 
 */
public class Molecule implements Specie, Comparable<Molecule> {

  /**
   * Name of this molecule.
   */
  private String name;

  /**
   * Molecule abundance.
   */
  private Double abundance;

  /**
   * Atomic fraction within this molecule.
   */
  private Double fraction;

  /**
   * This molecule atomic mass unit.
   */
  private Double amu;

  /**
   * Molecule velocity.
   */
  private Double velocity;

  /**
   * Holds probability of accretion.
   */
  private Double accretionProbability;

  /**
   * Holds accumulator value.
   */
  private Long accumulator;

  /**
   * Holds the type of Atom.
   */
  private String type;

  /**
   * Reports molecule activeness in the surface reactions.
   */
  private boolean isActive;

  /**
   * Instantiates new Molecule with predefined properties.
   * 
   * @param abundance new abundance value.
   * @param accretionProbability new accretionProbability value.
   * @param amu new amu value.
   * @param fraction new fraction value.
   * @param name new name value.
   * @param velocity new velocity value.
   */
  public Molecule(Double abundance, Double accretionProbability, Double amu, Double fraction,
      String name, String type, Double velocity, Long accumulator) {
    this.abundance = abundance;
    this.accretionProbability = accretionProbability;
    this.amu = amu;
    this.fraction = fraction;
    this.name = name;
    this.velocity = velocity;
    this.accumulator = accumulator;
    this.type = type;
    if (type.equalsIgnoreCase("active")) {
      this.isActive = true;
    }
  }

  /**
   * Initializes empty Molecule.
   * 
   */
  public Molecule() {
    this.abundance = 0.0;
    this.accretionProbability = 0.0;
    this.amu = 0.0;
    this.fraction = 0.0;
    this.name = null;
    this.velocity = 0.0;
    this.accumulator = 0L;
  }

  public String getName() {
    return this.name;
  }

  public void setAbundance(Double abundance) {
    this.abundance = abundance;
  }

  public Double getAbundance() {
    return this.abundance;
  }

  public void setAmu(Double amu) {
    this.amu = amu;
  }

  public Double getAmu() {
    return this.amu;
  }

  public void setVelocity(Double velocity) {
    this.velocity = velocity;
  }

  public Double getVelocity() {
    return this.velocity;
  }

  /**
   * Lame name comparator.
   * 
   * @param molecule molecule to compare with.
   * @return comparison result.
   */
  public int compareTo(Molecule molecule) {
    return this.name.compareTo(molecule.getName());
  }

  /**
   * Lame equal function.
   * 
   * @param molecule - object to compare with.
   * @return comparison result.
   */
  public boolean equals(Molecule molecule) {
    return this.name.equalsIgnoreCase(molecule.getName());
  }

  /**
   * Lame hashcode function.
   * 
   * @return lame hashcode.
   */
  @Override
  public int hashCode() {
    return 37 * this.name.hashCode() + this.name.hashCode();
  }

  public void setName(String name) {
    this.name = name;
  }

  public void setFraction(Double fraction) {
    this.fraction = fraction;
  }

  public Double getFraction() {
    return this.fraction;
  }

  public Double getRate(Double grainSize) {
    return this.abundance * this.velocity * Math.PI * grainSize;
  }

  public void setAccretionProbability(Double p) {
    this.accretionProbability = p;
  }

  public Double getAccretionProbability() {
    return this.accretionProbability;
  }

  public Long getAccumulatorValue() {
    return this.accumulator;
  }

  public void incrementAccumulatorValue(Long inc) {
    this.accumulator += inc;

  }

  public void setAccumulatorValue(Long value) {
    this.accumulator = value;

  }

  public Specie clone() {
    // public Atom(Double abundance, Double accretionProbability, Double amu, Double fraction,
    // String name, Double velocity, Long accumulator) {
    return new Molecule(this.abundance, this.accretionProbability, this.amu, this.fraction,
        this.name, this.type, this.velocity, this.accumulator);
  }

  public void decrementAccumulatorValue(long dec) {
    this.accumulator -= dec;
  }

  public String getType() {
    return this.type;
  }

  public void setType(String type) {
    this.type = type;
  }

  public String toText() {
    StringBuffer sb = new StringBuffer(1000);
    sb.append(this.name + ": ");
    sb.append(", amu: " + this.amu);
    sb.append(", abundance: " + this.abundance);
    sb.append(", fr: " + this.fraction);
    sb.append(", vel: " + this.velocity + "\n");

    return sb.toString();
  }

  public boolean isActive() {
    return this.isActive;
  }
}
